#include <toolpack.h>
#include <string>
#include <iostream>
#include <sstream>

using namespace std;

string  WstawCyfreRzymska(const int num,const char one,const char  five, const char ten );


int NaArabska(const string rzymskie)
{

	int sum = 0;
	bool pom = false;
	int add = 0;
	int min = 0;

	for (int i=0; i<(int)rzymskie.length();i++)
	{
		add = 0;
		min = 0;

		if (pom == false)
		{
			switch(rzymskie[i])
			{
					break;
				case 'M':
					add = 1000;
					break;
				case 'D':
					add = 500;
					break;
				case 'C':
					add = 100;
					break;
				case 'L':
					add = 50;
					break;
				case 'X':
					add = 10;
					break;
				case 'V':
					add = 5;
					break;
				case 'I':
					add = 1;
					break;
				default:
					return -1;
			}

			switch(rzymskie[i + 1])
			{
				case 'M': 
					min = 1000;
					break;
				case 'D':
					min = 500;
					break;
				case 'C':
					min = 100;
					break;
				case 'L':
					min = 50;
					break;
				case 'X':
					min = 10;
					break;
				case 'V':
					min = 5;
					break;
				case 'I':
					min = 1;
					break;
				default :
					min = 0;
			}

			if (add < min)
			{
				add = min - add;
				pom = true;
			}
			sum = sum + add;
		}
		else
		  pom = false;
	}

	return sum;
}

string NaRzymska(const int liczba)
{
 
	string Rzymska="";
	int number = liczba;

	if( (liczba/1000) > 0)
	{
      for(int i=0; i<liczba/1000;i++)
        Rzymska += 'M';
      number = number%1000;
	}

  if( (number/100) > 0 )
  {
      Rzymska += WstawCyfreRzymska(number/100,'C','D','M');
      number = number%100;
  }

  if( (number/10) > 0)
  {
      Rzymska += WstawCyfreRzymska(number/10,'X','L','C');
      number = number%10;
  }

  if(number > 0)
    Rzymska += WstawCyfreRzymska(number,'I','V','X');

  return Rzymska;

}

int DajWartoscRzymskiejCyfry(const char cyfra)
{
	for(int i=0; i<ileRzymskichCyfr;i++)
		if(rzymskieCyfrySymbole[i]==cyfra)
			return rzymskieCyfryWartosci[i];
	return -1;
}

string  WstawCyfreRzymska(const int num,const char one,const char  five, const char ten )
{
int i=0; 
string T="";

if( num < 4)
	for(int i=0;i<num;i++)
		T+=one;
else if(num == 4)
{
	T=one;
	T+=five;
}
else if( num == 5)
		T = five;
else if (num > 5 && num < 9) 
{
	T=five;
	for(int i=0; i<num-5;i++)
		T+=one;
}
else if (num == 9)
{
	T=one;
	T+=ten;
}

return T;
}

bool CzyRzymska(const string rzymska)
{
	int liczba = NaArabska(rzymska);
	string rzym2 = NaRzymska(liczba);
	if(rzym2==rzymska)
		return true;
	else
		return false;
}

//spr czy string jest liczba
bool CzyArabska(const string tekst)
{
	int liczba;
	string rest="";
	stringstream stream;

	//ladujemy tekst
	stream<<tekst;
	
	//odczytujemy liczbe
	stream>>liczba;
	//jezeli odczyt sie nie powiodl to blad
	if(stream.fail())
		return false;
	
	//spr czy zostalo cos w buforze
	stream>>rest;

	//jezeli zostalo to znaczy ze nie caly string da sie zamienic np: 123ea
	if(rest!="")
		return false;

	return true;
}

bool CzyRzymskieZnaki(const string tekst)
{
	for(unsigned int i=0; i<tekst.length();i++)
	{
		if(tekst[i]!=rzymskieCyfrySymbole[0]&&
			tekst[i]!=rzymskieCyfrySymbole[1]&&
			tekst[i]!=rzymskieCyfrySymbole[2]&&
			tekst[i]!=rzymskieCyfrySymbole[3]&&
			tekst[i]!=rzymskieCyfrySymbole[4]&&
			tekst[i]!=rzymskieCyfrySymbole[5])
			return false;
	}

	return CzyRzymska(tekst);
}

//funkcja usuwa nawiasy jesli otaczaja caly tekst
//np (text) -> tekst
//ale (text)()	-> (tekst)()
string UsunSkrajneNawiasy(const string tekst)
{
	string wynik = tekst;

	if(CzyZawartyWNawiasach(tekst))
		wynik = tekst.substr(1,tekst.length()-2);
	
	return wynik;
}

//zwraca pozycje nawiasu zamykajacego nawias znajdujacy sie na pozycji idx
//np: ZnajdzZamykajacyNawias("a(b(c))",1) == 6
int ZnajdzZamykajacyNawias(const string tekst,const int idx)
{
	int nawiasy=0;

	//jezeli indeks wykracza poza tekst to blad
	if((int)tekst.length()<=idx)
		return -1;

	//jezeli na podanej pozycji nie ma nawiasu otwierajacego to blad
	if(tekst[idx]!='(')
		return -1;

	for(unsigned int i=idx;i<tekst.length();i++)
	{
		if(tekst[i]=='(')
			nawiasy++;
		else if(tekst[i]==')')
			nawiasy--;

		//jezeli znalezlismy zamykajacy to zwracamy jego indeks
		if(nawiasy==0)
			return i;
	}
	
	return -1;
}

//funkcja sprawdza czy wszytkie nawiasy maja zamkniecie itp.
bool SprawdzNawiasy(const string tekst)
{
	int nawiasy=0;

	for(unsigned int i=0; i<tekst.length();i++)
	{
		if(tekst[i]==')')
			nawiasy--;
		else if(tekst[i]=='(')
			nawiasy++;

		if(nawiasy<0)
			return false;
	}
	
	if(nawiasy==0)
		return true;

	return false;
}


//funkcja sprawdza czy tekst jest zawarty w nawiasach
//np: (as(2))<-true, ale (a)(b)<-false 
bool CzyZawartyWNawiasach(const string tekst)
{
	if(tekst.length()<1)
		return false;
	
	if(tekst[0]!='(')
		return false;

	int idx=ZnajdzZamykajacyNawias(tekst,0);
	if(idx==tekst.length()-1)
		return true;
	else
		return false;
	

}

string ZakodujEscape(const string tekst)
{
	char z='\0';
	string Zwrot;
	string kod;

	for(int i=0; i<(int)tekst.length();i++)
	{
		z=tekst[i];
		if(IsAscii(z))
			kod=z;
		else
		{
			if(z=='('||z==')'||z=='('||z=='-'||z=='(')
				kod=z;
			else
				kod = ZamienZnakNaKod(z);
		}
		Zwrot+=kod;
	}
	return Zwrot;
}

string OdkodujEscape(const string tekst)
{
	char z='\0';
	string symbol;
	string zwrot="";

	for(int i=0; i<(int)tekst.length();i++)
	{
		z=tekst[i];
		if(z!='%')
			symbol=z;
		else
		{
			symbol = tekst.substr(i,6);
			symbol = ZamienKodNaZnak(symbol);
			//dodajemy 5 a nie 6 bo przy nastepnym obiegu petli i tak i zwiekszy sie o 1
			i+=5;
		}
		zwrot+=symbol;
	}

	return zwrot;
}


bool IsAscii(const char z)
{
	//wielkie znaki ASCII
	if((int)z>64&&(int)z<91)
		return true;

	//male znaki ascii
	else if((int)z>96&&(int)z<123)
		return true;

	//cyfry ascii
	else if((int)z>47&&(int)z<58)
		return true;

	//pozostale
	return false;
}


string ZamienZnakNaKod(const char znak)
{
	for(int i =0; i<IleKodowychZnakow;i++)
		if(znak==TablicaEscapeZnaki[i])
			return TablicaEscapeKody[i];

	return "";
}

char ZamienKodNaZnak(const string kod)
{
	for(int i =0; i<IleKodowychZnakow;i++)
		if(kod==TablicaEscapeKody[i])
			return TablicaEscapeZnaki[i];

	return '\0';
}


//sprawdza czy znak jest litera lub liczba (polskie znaki zwracaja false)
int ascIsAlnum(const char z)
{	
	//wielkie znaki ASCII
	if((int)z>64&&(int)z<91)
		return 1;

	//male znaki ascii
	else if((int)z>96&&(int)z<123)
		return 1;

	//cyfry ascii
	else if((int)z>47&&(int)z<58)
		return 1;

	//pozostale
	else
		return 0;
}
